package mathy.wili.extract_srcFile.java;
import java.io.File;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import _a.Config26;
import mathy.c.Ca;
import mathy.wili.c.Class9;
import mathy.wili.c.Str9;
import net.bytebuddy.jar.asm.MethodVisitor;
/**
 * 	代码提取上下文相关信息
 * @author weila 2021年2月25日
 */
@SuppressWarnings("rawtypes")
public class Cont26 {
	public int logedFileNum, extractFileNum;

	public static long copiedNum, totalSize, extractSize;

	/**
	 *  class ~> implement class List. 用来提供一个名义类的所有可能的实现类。
	 */
	public static final Map<Class, List<Class<?>>> IMP_clsMap = new HashMap<>();

	public static Cont26 INST = new Cont26();

	public static final AsmItemList toList = new AsmItemList(null);

	public static final Set<Class<?>> visitedClsSet = new HashSet<>();

	/**
	 * 	必将原样拷贝到目标目录下的源文件。某些文件或需深入访问（以提取其中引用到的，其它类中的元素）。
	 */
	public static final Set<Class<?>> filesMustBeCopied = new HashSet<>();
	public static void addMustBeCopiedFile(Class<?> cls) {
		filesMustBeCopied.add(cls);
	}

	/**
	 * 	把实现类，映射到其所有的超类和接口
	 */
	public static void visitConcreteClass_andItsSuperClass(Class<?> cls) {
		//未使用，保留之。
		//但它也非最优办法。最优办法是跟踪名义类的实现类，在访问名义类成员的时候，同步访问实现类的成员。
		if (cls.equals(MethodVisitor.class))
			Ca.pause();
		if (!Cont26.visitedClsSet.add(cls))
			return;
		int mod = cls.getModifiers();
		if (Modifier.isAbstract(mod))
			return;
		Class9.findClassUpwards(cls, new Consumer<Class<?>>() {
			@Override
			public void accept(Class<?> superCls) {
				if (cls == superCls)
					return;
				List<Class<?>> lis = IMP_clsMap.get(superCls);
				if (lis == null) {
					IMP_clsMap.put(superCls, lis = new ArrayList<>(5));
					lis.add(cls);
				} else if (!lis.contains(cls)) {
					lis.add(cls);
				}
			}
		});
	}

	private Cont26() {
	}

	public static File getToSrcRoot() {
		return Config26.Extract_toSourceDir;
	}

	public void extract(long fileSize, int size) {
		extractFileNum++;
		totalSize += fileSize;
		extractSize += size;
	}

	public void print() {
		double rate = extractSize / (double) totalSize;
		Ca.warn(1, "\n" + copiedNum, " files copied, and extract ",
				Str9.percentStrOf(rate, 0) + " code from " + extractFileNum + " files.");
	}
	/**
	 * 	一个java文件可能有并列的n个根类。第1个算是头类。
	 */
	static final Map<Class<?>, Class<?>> ClsToHeadClsMap = new HashMap<>();

	/**
	 * If not, will get help from insertLog version.
	 */
	public static final Boolean useAsmOnly = "".isEmpty();

	static List<String> msgList = new ArrayList<>();

	/**
	 * 	被提取出的代码所需要的 jar包。
	 */
	public static final Set<String> JarFileList = new HashSet<>();
}
